| Autor: Spinelli, Julián C. |
El siguiente informe pretende brindar cierta información respecto de los recorridos realizados mediante el uso de las bicicletas administradas por el Gobierno de la Ciudad de Buenos Aires, también conocidas como “ecobicis”. Para esto utilizaremos los datos publicados por el propio gobierno, realizando un recorte entre los años 2015-2021. Esto se debe a que los datos de años anteriores no se encuentran disponibles, por el momento.
En primer lugar, procedemos a cargar las librerías a utilizar:
library(tidyverse) # Set de herramientas inicial
library(lubridate) # Manejo de Fechas
library(viridis) # Escala de colores
library(plotly) # Interacción entre visualizaciones
library(kableExtra) # Visualizaciones de tablas
Luego, insertamos los dataframes correspondientes:
bicicletas_2015 <- read_csv("recorridos-realizados-2015.csv")
bicicletas_2016 <- read_csv("recorridos-realizados-2016.csv")
bicicletas_2017 <- read_csv("recorridos-realizados-2017.csv")
bicicletas_2018 <- read_csv("recorridos-realizados-2018.csv")
bicicletas_2019 <- read_csv("recorridos-realizados-2019.csv")
bicicletas_2020 <- read_csv("recorridos_realizados_2020.csv")
bicicletas_2021 <- read_csv("recorridos_realizados_2021.csv")
Primera aproximación del contenido que proveen los dataframes:
| id_recorrido | Duracion Recorrido | fecha_origen_recorrido | id_estacion_origen | nombre_estacion_origen | direccion_estacion_origen | long_estacion_origen | lat_estacion_origen | fecha_destino_recorrido | id_estacion_destino | nombre_estacion_destino | direccion_estacion_destino | long_estacion_destino | lat_estacion_destino | id_usuario | modelo_bicicleta |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 10758473BAEcobici | 591 | 2021-04-10 20:38:24 UTC | 2BAEcobici | 002 - Retiro I | Ramos Mejia, Jose Maria, Dr. Av. & Del Libertador Av. | -58.37472 | -34.59242 | 2021-04-10 20:48:15 UTC | 95BAEcobici | 095 - ESMERALDA | ESMERALDA 516 | -58.37817 | -34.60211 | 86840BAEcobici | ICONIC |
| 10757803BAEcobici | 1321 | 2021-04-10 16:34:08 UTC | 2BAEcobici | 002 - Retiro I | Ramos Mejia, Jose Maria, Dr. Av. & Del Libertador Av. | -58.37472 | -34.59242 | 2021-04-10 16:56:09 UTC | 73BAEcobici | 073 - Ruy Díaz de Guzmán | Avenida Martin Garcia y Ruy Díaz de Guzmán | -58.37182 | -34.63068 | 52860BAEcobici | ICONIC |
| 10756603BAEcobici | 380 | 2021-04-10 07:06:00 UTC | 3BAEcobici | 003 - ADUANA | Moreno & Av Paseo Colon | -58.36826 | -34.61103 | 2021-04-10 07:12:20 UTC | 150BAEcobici | 150 - RODRIGO BUENO | Av. España 2200 | -58.35547 | -34.61875 | 375594BAEcobici | ICONIC |
| 10756618BAEcobici | 1436 | 2021-04-10 07:25:08 UTC | 4BAEcobici | 004 - Plaza Roma | Lavalle & Bouchard | -58.36878 | -34.60182 | 2021-04-10 07:49:04 UTC | 353BAEcobici | 237 - Madero Office | 367 Sanchez De Thompson, Mariquita | -58.36469 | -34.59904 | 489972BAEcobici | ICONIC |
| 10757830BAEcobici | 3736 | 2021-04-10 16:45:01 UTC | 4BAEcobici | 004 - Plaza Roma | Lavalle & Bouchard | -58.36878 | -34.60182 | 2021-04-10 17:47:17 UTC | 207BAEcobici | 123 - BASUALDO Y RODO | Basualdo 1218 | -58.49263 | -34.64932 | 77965BAEcobici | ICONIC |
| 10757832BAEcobici | 3681 | 2021-04-10 16:45:11 UTC | 4BAEcobici | 004 - Plaza Roma | Lavalle & Bouchard | -58.36878 | -34.60182 | 2021-04-10 17:46:32 UTC | 207BAEcobici | 123 - BASUALDO Y RODO | Basualdo 1218 | -58.49263 | -34.64932 | 764009BAEcobici | ICONIC |
A continuación procedemos a recopilar la información que utilizaremos de los distintos dataframes y realizar una limpieza y normalización de los mismos:
glimpse(bicicletas_2015)
## Rows: 503,252
## Columns: 15
## $ periodo <dbl> 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2…
## $ genero_usuario <chr> "M", "F", "M", "M", "M", "F", "M", "F", "M"…
## $ fecha_origen_recorrido <dttm> 2015-05-01 00:00:18, 2015-05-01 00:02:06, …
## $ id_estacion_origen <dbl> 25, 17, 17, 29, 29, 1, 30, 1, 4, 36, 18, 28…
## $ nombre_estacion_origen <chr> "Plaza Güemes", "Plaza Almagro", "Plaza Alm…
## $ long_estacion_origen <dbl> -58.41607, -58.41883, -58.41883, -58.43458,…
## $ lat_estacion_origen <dbl> -34.58952, -34.60640, -34.60640, -34.60846,…
## $ domicilio_estacion_origen <chr> "Salguero Jerónimo y Mansilla", "Plaza Alma…
## $ duracion_recorrido <chr> "0 days 00:26:24.000000000", "0 days 00:57:…
## $ fecha_destino_recorrido <dttm> 2015-05-01 00:26:42, 2015-05-01 00:59:59, …
## $ id_estacion_destino <dbl> 29, 25, 25, 25, 25, 25, 30, 25, 18, 7, 9, 2…
## $ nombre_estacion_destino <chr> "Parque Centenario", "Plaza Güemes", "Plaza…
## $ long_estacion_destino <dbl> -58.43458, -58.41607, -58.41607, -58.41607,…
## $ lat_estacion_destino <dbl> -34.60846, -34.58952, -34.58952, -34.58952,…
## $ domicilio_estacion_destino <chr> "Patricias Argentinas y Carlos Finlay", "Sa…
glimpse(bicicletas_2017)
## Rows: 1,048,158
## Columns: 15
## $ periodo <dbl> 2017, 2017, 2017, 2017, 2017, 2017, 2017, 2…
## $ genero_usuario <chr> "M", "M", "M", "M", "M", "F", "M", "M", "F"…
## $ fecha_origen_recorrido <dttm> 2017-01-01 00:02:14, 2017-01-01 00:02:59, …
## $ id_estacion_origen <dbl> 60, 79, 11, 79, 150, 79, 85, 48, 26, 79, 24…
## $ nombre_estacion_origen <chr> "25 de Mayo", "Azucena Villaflor", "Tribuna…
## $ long_estacion_origen <dbl> -58.37116, -58.36397, -58.38502, -58.36397,…
## $ lat_estacion_origen <dbl> -34.60164, -34.61172, -34.60131, -34.61172,…
## $ domicilio_estacion_origen <chr> "25 de Mayo y Lavalle", "Azucena Villaflor …
## $ duracion_recorrido <chr> "0 days 00:27:44.000000000", "0 days 01:57:…
## $ fecha_destino_recorrido <dttm> 2017-01-01 00:28:38, 2017-01-01 01:00:52, …
## $ id_estacion_destino <dbl> 4, 54, 84, 74, 1, 74, 20, 96, 68, 17, 79, 4…
## $ nombre_estacion_destino <chr> "Plaza Roma", "Acuña de Figueroa", "Lavalle…
## $ long_estacion_destino <dbl> -58.36895, -58.42170, -58.39547, -58.43424,…
## $ lat_estacion_destino <dbl> -34.60172, -34.59822, -34.60229, -34.60457,…
## $ domicilio_estacion_destino <chr> "Lavalle y Bouchard", "Lavalle y Acuña de F…
glimpse(bicicletas_2021)
## Rows: 2,649,845
## Columns: 16
## $ id_recorrido <chr> "10758473BAEcobici", "10757803BAEcobici", "…
## $ `Duracion Recorrido` <dbl> 591, 1321, 380, 1436, 3736, 3681, 3713, 250…
## $ fecha_origen_recorrido <chr> "2021-04-10 20:38:24 UTC", "2021-04-10 16:3…
## $ id_estacion_origen <chr> "2BAEcobici", "2BAEcobici", "3BAEcobici", "…
## $ nombre_estacion_origen <chr> "002 - Retiro I", "002 - Retiro I", "003 - …
## $ direccion_estacion_origen <chr> "Ramos Mejia, Jose Maria, Dr. Av. & Del Lib…
## $ long_estacion_origen <dbl> -58.37472, -58.37472, -58.36826, -58.36878,…
## $ lat_estacion_origen <dbl> -34.59242, -34.59242, -34.61103, -34.60182,…
## $ fecha_destino_recorrido <chr> "2021-04-10 20:48:15 UTC", "2021-04-10 16:5…
## $ id_estacion_destino <chr> "95BAEcobici", "73BAEcobici", "150BAEcobici…
## $ nombre_estacion_destino <chr> "095 - ESMERALDA", "073 - Ruy Díaz de Guzmá…
## $ direccion_estacion_destino <chr> "ESMERALDA 516", "Avenida Martin Garcia y R…
## $ long_estacion_destino <dbl> -58.37817, -58.37182, -58.35547, -58.36469,…
## $ lat_estacion_destino <dbl> -34.60211, -34.63068, -34.61875, -34.59904,…
## $ id_usuario <chr> "86840BAEcobici", "52860BAEcobici", "375594…
## $ modelo_bicicleta <chr> "ICONIC", "ICONIC", "ICONIC", "ICONIC", "IC…
Lo primero que surge de esta breve exploración es que, en los distintos sets, conviven mismas variables con distintos tipos de datos (id_estacion_origen; id_estacion_destino; fecha_origen_recorrido; fecha_destino_recorrido; duracion_recorrido). Si observamos detenidamente, algunos se encuentran representados como characters, mientras que entros frames, aparecen como datetime. Con lo cual, lo primero que debemos hacer es homogeneizar estos tipos de datos, para luego no tener un error al momento de recopilar los data sets.
bicicletas_2015 <- bicicletas_2015 %>%
mutate(id_estacion_origen = as.character(id_estacion_origen))%>%
mutate(id_estacion_destino = as.character(id_estacion_destino))%>%
mutate(fecha_origen_recorrido = ymd_hms(fecha_origen_recorrido)) %>%
mutate(fecha_destino_recorrido = ymd_hms(fecha_destino_recorrido))
bicicletas_2016 <- bicicletas_2016 %>%
mutate(id_estacion_origen = as.character(id_estacion_origen))%>%
mutate(id_estacion_destino = as.character(id_estacion_destino))%>%
mutate(fecha_origen_recorrido = ymd_hms(fecha_origen_recorrido)) %>%
mutate(fecha_destino_recorrido = ymd_hms(fecha_destino_recorrido))
bicicletas_2017 <- bicicletas_2017 %>%
mutate(id_estacion_origen = as.character(id_estacion_origen))%>%
mutate(id_estacion_destino = as.character(id_estacion_destino))
bicicletas_2018 <- bicicletas_2018 %>%
mutate(id_estacion_origen = as.character(id_estacion_origen))%>%
mutate(id_usuario = as.character(id_usuario))%>%
mutate(id_estacion_destino = as.character(id_estacion_destino))
bicicletas_2019 <-bicicletas_2019 %>%
mutate(fecha_origen_recorrido = ymd_hms(fecha_origen_recorrido)) %>%
mutate(fecha_destino_recorrido = ymd_hms(fecha_destino_recorrido))%>%
mutate(duracion_recorrido = as.character(duracion_recorrido))
bicicletas_2020 <-bicicletas_2020 %>%
mutate(fecha_origen_recorrido = ymd_hms(fecha_origen_recorrido)) %>%
mutate(fecha_destino_recorrido = ymd_hms(fecha_destino_recorrido))%>%
mutate(duracion_recorrido = as.character(duracion_recorrido))
bicicletas_2021 <-bicicletas_2021 %>%
mutate(fecha_origen_recorrido = ymd_hms(fecha_origen_recorrido)) %>%
mutate(fecha_destino_recorrido = ymd_hms(fecha_destino_recorrido))%>%
mutate(duracion_recorrido = as.character(`Duracion Recorrido`))%>%
select(-`Duracion Recorrido`)
Una vez realizado este proceso, procedemos a construir un solo dataframe que contenga las variables desde el 2015 hasta el 2021:
bicicletas_2015_2021 <- bind_rows(bicicletas_2015,bicicletas_2016,bicicletas_2017,bicicletas_2018,bicicletas_2019,bicicletas_2020,bicicletas_2021)
Ya con el dataframe contenedor creado, removemos los dataframes que no utilizaremos, manteniendo únicamente el que corresponde al 2015-2021:
rm(bicicletas_2015, bicicletas_2016, bicicletas_2017,bicicletas_2018,bicicletas_2019,bicicletas_2020,bicicletas_2021)
Aqui nos encargamos de limpiar los datos de la variable “Duración Recorrido” en el dataframe, dado que contiene una multiplicidad de caracteres variados. Utilizando la función clean_names() de la libreria janitor nos encargaremos de estandarizar los datos de dicha variable:
bicicletas_2015_2021_cleaned <- bicicletas_2015_2021 %>%
janitor::clean_names()
| periodo | genero_usuario | fecha_origen_recorrido | id_estacion_origen | nombre_estacion_origen | long_estacion_origen | lat_estacion_origen | domicilio_estacion_origen | duracion_recorrido | fecha_destino_recorrido | id_estacion_destino | nombre_estacion_destino | long_estacion_destino | lat_estacion_destino | domicilio_estacion_destino | id_usuario | id_recorrido | direccion_estacion_origen | direccion_estacion_destino | modelo_bicicleta |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2015 | M | 2015-05-01 00:00:18 | 25 | Plaza Güemes | -58.41607 | -34.58952 | Salguero Jerónimo y Mansilla | 0 days 00:26:24.000000000 | 2015-05-01 00:26:42 | 29 | Parque Centenario | -58.43458 | -34.60846 | Patricias Argentinas y Carlos Finlay | NA | NA | NA | NA | NA |
| 2015 | F | 2015-05-01 00:02:06 | 17 | Plaza Almagro | -58.41883 | -34.60640 | Plaza Almagro | 0 days 00:57:53.000000000 | 2015-05-01 00:59:59 | 25 | Plaza Güemes | -58.41607 | -34.58952 | Salguero Jerónimo y Mansilla | NA | NA | NA | NA | NA |
| 2015 | M | 2015-05-01 00:02:53 | 17 | Plaza Almagro | -58.41883 | -34.60640 | Plaza Almagro | 0 days 01:03:08.000000000 | 2015-05-01 01:06:01 | 25 | Plaza Güemes | -58.41607 | -34.58952 | Salguero Jerónimo y Mansilla | NA | NA | NA | NA | NA |
| 2015 | M | 2015-05-01 00:08:01 | 29 | Parque Centenario | -58.43458 | -34.60846 | Patricias Argentinas y Carlos Finlay | 0 days 01:04:18.000000000 | 2015-05-01 01:12:19 | 25 | Plaza Güemes | -58.41607 | -34.58952 | Salguero Jerónimo y Mansilla | NA | NA | NA | NA | NA |
| 2015 | M | 2015-05-01 00:08:57 | 29 | Parque Centenario | -58.43458 | -34.60846 | Patricias Argentinas y Carlos Finlay | 0 days 01:09:41.000000000 | 2015-05-01 01:18:38 | 25 | Plaza Güemes | -58.41607 | -34.58952 | Salguero Jerónimo y Mansilla | NA | NA | NA | NA | NA |
| 2015 | F | 2015-05-01 00:09:06 | 1 | Facultad de Derecho | -58.39245 | -34.58313 | Av. Pres.Figueroa Alcorta y Juan A.Bibiloni | 0 days 01:21:27.000000000 | 2015-05-01 01:30:33 | 25 | Plaza Güemes | -58.41607 | -34.58952 | Salguero Jerónimo y Mansilla | NA | NA | NA | NA | NA |
Por ultimo, procedemos a remover bicicletas_2015_2021:
rm(bicicletas_2015_2021)
Como primer paso, verificamos cuál es la estación con mayor demanda de bicicletas :
Estacion_mayor_demanda <- bicicletas_2015_2021_cleaned %>%
count(nombre_estacion_origen,
sort = T,
name = 'cantidad_salidas')%>%
top_n(10)
| nombre_estacion_origen | cantidad_salidas |
|---|---|
| 147 - Constitución | 137918 |
| 014 - Pacifico | 127443 |
| 029 - Parque Centenario | 108068 |
| Parque Las Heras | 107270 |
| 160 - Godoy Cruz y Libertador | 95172 |
| 009 - Parque Las Heras | 94408 |
Lo que devuelve esta operación es que la estación 147 - Constitución es la más demandada durante este periodo. En consecuencia, trabajaremos con ella de ahora en adelante.
Lo primero que debemos realizar es una reducción de los datos para recibir únicamente las salidas de la estación 147 - Constitución . Luego, filtraremos también para que el lugar de devolución de la bicicleta no sea la estación desde donde se retiró la misma. Una vez realizado este proceso, usaremos la función count() para verificar la frecuencia de la variable categórica nombre_estacion_destino.
destinos_desde_constitucion <- bicicletas_2015_2021_cleaned %>%
filter(nombre_estacion_origen == '147 - Constitución' &
nombre_estacion_destino != '147 - Constitución') %>%
count(nombre_estacion_destino,
sort = T,
name = 'cantidad_salidas_desde_constitucion')
Al generar nuestra primera visualización utilizaremos los primeros diez valores para que el gráfico sea interpretable:
destinos_desde_constitucion %>%
top_n(10, cantidad_salidas_desde_constitucion) %>%
ggplot(aes(x=reorder(nombre_estacion_destino,
cantidad_salidas_desde_constitucion),
weight=cantidad_salidas_desde_constitucion))+
geom_bar(aes(fill = factor(nombre_estacion_destino))) +
scale_fill_viridis(discrete = T) +
theme_minimal() +
theme(legend.position = "none") +
coord_flip() +
labs(x = 'Estación',
y = 'Cantidad de llegadas',
title = 'Cantidad de llegadas por estación',
subtitle = 'desde Constitución',
caption = 'Fuente de datos: https://data.buenosaires.gob.ar/')
En primer lugar, vamos a crear un pequeño dataframe con los datos discriminados de nuestra estación. Esto es, los viajes salidos desde la estación constitución y que no volvieron a la estación como destino.
bicicletas_2015_2021_constitucion<-bicicletas_2015_2021_cleaned %>%
filter(nombre_estacion_origen == '147 - Constitución' | nombre_estacion_origen == 'Constitución',
nombre_estacion_destino != nombre_estacion_origen)
Luego modificamos fecha_origen_recorrido para que se visualice la fecha sin horario mediante as_date() . Finalmente, implementamos la función un count() para calcular la frecuencia de cada fecha.
viajes_desde_constitucion_fecha <- bicicletas_2015_2021_constitucion %>%
mutate(fecha_de_inicio = parse_date_time(fecha_origen_recorrido, 'ymd HMS'),
dia_inicio = as_date(fecha_de_inicio)) %>%
count(dia_inicio)
visualizacion_viajes_por_fecha <- viajes_desde_constitucion_fecha %>%
ggplot(aes(x=dia_inicio, y = n)) +
geom_line(color = 'green3', size = 1.5)+
theme_minimal() +
theme(legend.position = "none") +
labs(x = 'Dia',
y = 'Cantidad de salidas',
title = 'Cantidad de salidas por día desde Constitución')
ggplotly(visualizacion_viajes_por_fecha, tooltip = c("x", "y"))
La información que nos ha devuelto esta visualización resulta interesante. Si observamos el gráfico, previo al 2019 no hay datos respecto de la estación 147 - Constitución .
Para continuar, nos proponemos verificar qué día de la semana fue el más demandado en nuestro recorte temporal.
Primero, crearemos una variables que nos permita distinguir los días de la semana en nuestra variable dia_inicio.
viajes_desde_constitucion_fecha$dia_semana_salida <- weekdays(viajes_desde_constitucion_fecha$dia_inicio)
Con esta información, vamos a sumar la cantidad de salidas por fechas, pero agrupada según los días de la semana. Luego, la ordenaremos para verificar que día se dió la mayor cantidad de retiros.
viajes_desde_constitucion_semana <- viajes_desde_constitucion_fecha %>%
group_by(dia_semana_salida) %>%
summarise(Cantidad_salidas_por_dia = sum(n)) %>%
arrange(desc(Cantidad_salidas_por_dia))
Por último, realizamos la visualización de los mismos en un gráfico de barras, ordenado por los días de la semana:
visualización_viajes_constitucion_semana <-viajes_desde_constitucion_semana %>%
ggplot(aes(x= fct_relevel(
dia_semana_salida,
"lunes",
"martes",
"miércoles",
"jueves",
"viernes",
"sábado",
"domingo"
), y=Cantidad_salidas_por_dia, fill = dia_semana_salida, label = Cantidad_salidas_por_dia)) +
geom_bar(stat = "identity")+
geom_text(size = 3,
position = position_stack(vjust = 0.5),
colour = 'white') +
labs(x = '',
y = '',
title = 'Cantidad de salidas por día de la semana',
subtitle = 'desde Constitución (2019-2021)',
caption = 'Fuente de datos: https://data.buenosaires.gob.ar/') +
theme(legend.position = "none")
Como podemos observar, el día Miercoles fue el día que más salidas hubo desde la estación 147 - Constitución con un total de 22881 salidas en el periodo 2019-2021.
Para finalizar, nos proponemos observar qué hora del día es la más demandada para la estación.
En primer lugar, crearemos dos variables que nos permiten separar la fecha del retiro de la bicicleta del horario en el que se produjo su retiro:
bicicletas_2015_2021_constitucion$dia_inicio <- as.Date(bicicletas_2015_2021_constitucion$fecha_origen_recorrido)
bicicletas_2015_2021_constitucion$hora_inicio <- format(as.POSIXct(bicicletas_2015_2021_constitucion$fecha_origen_recorrido) , format = "%H")
Una vez realizado este proceso, construimos un pequeño dataframe que contabilice la cantidad de salidas por hora:
viajes_desde_constitucion_hora <- bicicletas_2015_2021_constitucion %>%
count(hora_inicio,
sort = T,
name = 'cantidad_salidas_hora')
Por último, generamos la visualización de los datos obtenidos:
visualizacion_viajes_por_hora <-viajes_desde_constitucion_hora %>%
ggplot(aes(x= hora_inicio, y=cantidad_salidas_hora, fill = cantidad_salidas_hora, label = cantidad_salidas_hora, width= .8)) +
geom_bar(stat = "identity",width= 2)+
geom_text(size = 3,
position = position_stack(vjust = 0.5),
colour = 'white') +
coord_flip() +
labs(x = 'Hora',
y = 'Cantidad',
title = 'Cantidad de salidas por hora',
subtitle = 'desde Constitución (2019-2021)',
caption = 'Fuente de datos: https://data.buenosaires.gob.ar/') +
theme(legend.position = "none")
Como podemos observar, las 18hs aparece como la más demandada, con un total de 11585 retiros en nuestro recorte temporal.